package main

import (
	"fmt"
	"os"
)

func (cli *CLI) CreateBlockChain(address string) {
	if !IsValidAddress(address) {
		fmt.Printf("地址无效，请检查\n")
	}

	//3. 调用真正的添加区块函数
	bc := CreateBlockChain(address)
	if bc == nil {
		//fmt.Printf("创建区块链失败!")
		return
	}

	bc.Db.Close()
	fmt.Printf("创建区块链成功!\n")

	//重新load一次utxo
	gfLoadUtxoInfos()
}

func (cli *CLI) PrintChain() {
	bc := NewBlockChain()
	if bc == nil {
		//fmt.Printf("创建区块链失败!")
		return
	}
	defer bc.Db.Close()
	bc.PrintChain()
}

func (cli *CLI) PrintTx() {
	bc := NewBlockChain()
	if bc == nil {
		//fmt.Printf("创建区块链失败!")
		return
	}
	defer bc.Db.Close()

	it := bc.NewIterator()
	for {
		block := it.Next()
		fmt.Printf("++++++++++++++++++++++++++++++++++\n")
		for _, tx := range block.Transactions {
			fmt.Println(tx)
		}

		if len(block.PrevBlockHash) == 0 {
			break
		}
	}
}

func (cli *CLI) GetBalanceDb(address string) {
	fmt.Printf("00000000\n")
	if !IsValidAddress(address) {
		fmt.Printf("地址无效，请检查\n")
		return
	}

	bc := NewBlockChain()
	if bc == nil {
		//fmt.Printf("创建区块链失败!")
		return
	}
	defer bc.Db.Close()

	fmt.Printf("1111111111\n")
	detail, value := bc.GetBalanceDb(address)
	fmt.Printf("%s 的余额为: %s, %f\n", address, detail, value)
}

func (cli *CLI) GetBalanceMem(address string) {
	fmt.Printf("00000000\n")
	if !IsValidAddress(address) {
		fmt.Printf("地址无效，请检查\n")
		return
	}

	bc := NewBlockChain()
	if bc == nil {
		//fmt.Printf("创建区块链失败!")
		return
	}
	defer bc.Db.Close()

	fmt.Printf("1111111111\n")
	detail, value := bc.GetBalanceMem(address)
	fmt.Printf("%s 的余额为: %s, %f\n", address, detail, value)
}

func (cli *CLI) Send(from, to string, amount float64) {

	if !IsValidAddress(from) {
		fmt.Printf("from : %s 地址无效，请检查\n", from)
		return
	}

	if !IsValidAddress(to) {
		fmt.Printf("to : %s 地址无效，请检查\n", to)
		return
	}

	fmt.Printf("%s 向 %s 转账 %f\n", from, to, amount)

	bc := NewBlockChain()
	if bc == nil {
		fmt.Printf("xxxxxxx\n")
		return
	}
	defer bc.Db.Close()

	//txs := []*Transaction{coinbase}

	//2. 创建普通交易
	tx := NewTransaction(from, to, amount, bc)
	if tx != nil {
		//3. 添加交易到交易数组
		gTx = append(gTx, tx)
	} else {
		fmt.Printf("余额不足，创建交易失败\n")
	}
}

func (cli *CLI) Mine(miner, data string) {
	//1. 创建挖矿交易
	coinbase := NewCoinbaseTx(miner, data)
	gTx = append([]*Transaction{coinbase}, gTx...)

	bc := NewBlockChain()
	if bc == nil {
		return
	}
	defer bc.Db.Close()

	//4. 添加交易到区块链AddBlock
	invalidTxs := bc.AddBlock(gTx)

	if len(invalidTxs) != 0 {
		fmt.Printf("矿工发现无效交易，回滚内存!\n")
		//TODO
	}

	//需要最终更新一下gAllUtxoinfos结构，将lock的utxo删除 //TODO

	gfUpdateReceiverUtxoinfos()
	gfUpdateMinnerUtxoinfos(miner, coinbase)

	fmt.Printf("打包交易数量: %d\n", len(gTx) - 1)
	fmt.Printf("区块创建成功!\n")

	//应该清除全局gTx
	gTx = []*Transaction{}
	//清除收款人的集合
	gNewReceiverUtxoInfos = make(map[string][]UTXOInfo) //address -> utxoinfo集合
}

func (cli *CLI) CreateWallet() {
	//w := NewWallet()
	//address := w.GetAddress()
	ws := NewWallets()

	address := ws.CreateWallet()

	if address == "" {
		fmt.Printf("创建地址失败\n")
		os.Exit(1)
	}

	fmt.Printf("你的新地址为: %s\n", address)
}

func (cli *CLI) ListAllAddress(flag int64) {
	//1. 打开钱包
	//2. 遍历里面的map
	//3. 将所有的key（地址）返回来

	var bc *BlockChain

	if flag != 0 {
		bc = NewBlockChain()
		if bc == nil {
			fmt.Printf("请先创建区块链, 打印地址失败!\n")
			return
		}
		defer bc.Db.Close()
	}

	ws := NewWallets()
	//返回一个地址的数组
	addresses := ws.GetAddresses()

	for _, address := range addresses {
		if flag != 0 {
			totalstr, total := bc.GetBalanceMem(address)
			fmt.Printf("%s 的余额为: %s=%f\n\n", address, totalstr, total)
		} else {
			fmt.Printf("%s\n", address)
		}
	}
}

func (cli *CLI) Help() {
	fmt.Printf(Usage)
}

func (cli *CLI) Status() {
	fmt.Printf("待确认交易数量: %d\n", len(gTx))
}

func (cli *CLI) Reload() {
	fmt.Printf("重新加载utxo到内存!\n")
	gfLoadUtxoInfos()
}
